#ifndef __UDP_SERVER_HPP__
#define __UDP_SERVER_HPP__

#include<iostream>
#include<string>
#include<memory>
#include<cstring>
#include<cerrno>
#include<string.h>

#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<functional>

#include"InetAddr.hpp"
#include"Log.hpp"
#include"Common.hpp"
#include "ThreadPool.hpp"
using namespace std;
using namespace Log_M;
using namespace ThreadPoolModule;


//回调函数，实现耦合
//进行用户增加的任务
using fun_user_add=function<void(InetAddr &id)>;
//进行删除用户的任务
using fun_user_remove=function<void(InetAddr &id)>;
//进行用户发送信息的任务
using fun_user_send=function<void(int sockfd,string &messages)>;
//进行的任务
using fun_user_task=function<void()>;

class nocopy
{
   public:
   nocopy(){};
   const nocopy& operator=(const nocopy&)=delete;
   nocopy(const nocopy&)=delete;
   ~nocopy(){};
};

class Udp_server :public nocopy
{
    private:
    int _sockfd;
    InetAddr _addr;
    bool _isruning;
    fun_user_add _add;
    fun_user_remove _remove;
    fun_user_send _send;

    public:
    Udp_server(uint16_t port=8080)
    :_sockfd(-1),
    _addr(port),
    _isruning(false)
    {
    }

    void InitServer()
    {
        _sockfd=socket(AF_INET,SOCK_DGRAM,0);
        if(_sockfd<0)
        {
            Log(Log_Level::FATAL)<<"socket fail";
            Die(SCOKET_ERR);
        }
        Log(Log_Level::INFO)<<_sockfd+" 这是成功的sockfd,socket success";

        int n=bind(_sockfd,_addr.Netaddr(),_addr.NetAddrLen());
        if(n<0)
        {
            Log(Log_Level::FATAL)<<"bind";
            Die(BIND_ERR);
        }
        Log(Log_Level::INFO)<<"bind success";
    }

    void RegisterService(fun_user_add adduser, fun_user_send route, fun_user_remove removeuser)
    {
        _add= adduser;
        _send= route;
        _remove = removeuser;
    }

    void start()
    {
        _isruning=true;
        while(true)
        {
            char inbuffer[1024];
            struct sockaddr_in peer;
            socklen_t len=sizeof(peer);

            ssize_t n= recvfrom(_sockfd,inbuffer,sizeof(inbuffer)-1,0,Change(&peer),&len);
            if(n>0)
            {
                InetAddr client(peer);
                inbuffer[n]=0;
               string message;
               if(strcmp(inbuffer,"QUIT")==0)
               {
                  _remove(client);
                  message = client.Addr() + "该用户说" + "我走了，你们继续聊天!";
               }
               else{
                _add(client);
                message = client.Addr() + "该用户加入群聊并说" + inbuffer;
               }
                fun_user_task task = bind(Udp_server::_send, _sockfd, message);
                ThreadPool<fun_user_task>::getInstance()->Equeue(task);
            }        
        }
        _isruning=false;
    }
    ~Udp_server()
    {
        if(_sockfd>-1)
        {
            close(_sockfd);
        }
    }
};
#endif